<template>
  <el-container>
    <el-aside width="200px">
      <el-tree :data="treeData" default-expand-all @current-change="treeCurrentChange" :props="{class: customNodeClass }"  />
    </el-aside>
    <el-container>
      <el-main>
        <RelationGraph ref="graphRef$" :options="options" @contextmenu="handleRightClick" @node-click="handleNodeClick">
          <template #node="{ node }">
            <div style="width: 150px;height: 200px;background-color: #3783c0"
              class="graph-node-container" 
              :class="node.nodeShape ==1?'is-nodeShape':''"
              :data-node="JSON.stringify({ id: node.id, data: node.data, text: node.text })">
              <!-- 节点标题（支持重命名时的输入框切换） -->
              <div v-if="!editingNodeId || editingNodeId !== node.id">
                {{ node.text }}
              </div>
              <el-input v-else v-model="editingNodeText" class="node-edit-input" @blur="confirmRename(node.id)"
                @keyup.enter="confirmRename(node.id)" @keyup.esc="cancelRename" ref="editInputRef" />
              <table class="c-data-table">
                <tr>
                  <th>名称</th>
                  <th>类型</th>
                </tr>
                <template v-for="column of node.data.columns" :key="column.columnName">
                  <tr>
                    <td>
                      <div :id="`${node.id}-${column.name}`">{{ column.name }}</div>
                    </td>
                    <td>{{ column.type }}</td>
                  </tr>
                </template>
              </table>
            </div>
          </template>
        </RelationGraph>
        <!-- 1. 节点右键菜单（设计表/重命名/删除表） -->
        <div v-show="showNodeContextMenu" :style="nodeContextMenuStyle" class="context-menu" @click.stop>
          <div class="menu-item" @click="handleDesignTable">设计表</div>
          <div class="menu-item" @click="handleRenameNode">重命名</div>
          <div class="menu-item" @click="handleDeleteNode" style="color: #ff4d4f;">删除表</div>
        </div>
        <!-- 2. 空白处右键菜单（保留原有功能） -->
        <div v-show="showBlankContextMenu" :style="blankContextMenuStyle" class="context-menu" @click.stop>
          <div class="menu-item" @click="addNode">添加节点</div>
          <div class="menu-item" @click="clearGraph" v-if="isClear">清空图表</div>
          <!-- <div class="menu-item" @click="downloadGraph">下载图表</div> -->
        </div>
      </el-main>
      <el-footer>
        <el-button type="primary" @click="saveClick">保存</el-button>
      </el-footer>
    </el-container>
  </el-container>
  <DesignTableDialog :visible="showDesignDialog" :tableName="tableName" @cancel="cancel"
    @saveTableDesign="saveTableDesign" />
</template>

<script setup lang="ts">
import { onMounted, ref, nextTick, computed } from 'vue';
import RelationGraph from 'relation-graph-vue3'
import type { RelationGraphComponent, RGJsonData, RGNode } from 'relation-graph-vue3'
import { ElMessageBox, ElMessage } from "element-plus"
import DesignTableDialog from "@/components/designTableDialog.vue"
import { useApp } from '@/store/app.ts';
import { useForeignKey } from '@/store/foreignKey.ts';
const useForeignKeyStore = useForeignKey()
import { useField } from '@/store/field.ts';
const useFieldStore = useField()
import { storeToRefs } from "pinia"
const useAppStore = useApp()
const { treeData ,count,lines } = storeToRefs(useAppStore)

const graphRef$ = ref<RelationGraphComponent | null>(null)
const graphData = ref<RGJsonData>({
  rootId: 'root',
  nodes: [],
  lines: []
})
const options = {
  defaultExpandHolderPosition: 'right',
  allowNodeDrag: true,
  allowShowDownloadButton: false,
  layout: { layoutName: 'fixed' }
}
// 2. 右键菜单状态（区分节点右键/空白右键）
const showNodeContextMenu = ref(false) // 节点右键菜单显示状态
const showBlankContextMenu = ref(false) // 空白处右键菜单显示状态
const nodeContextMenuStyle = ref({ left: '0px', top: '0px', position: 'fixed', zIndex: 1000 })
const blankContextMenuStyle = ref({ left: '0px', top: '0px', position: 'fixed', zIndex: 1000 })
const currentNode = ref<RGNode | null>(null) // 当前右键点击的节点

// 3. 重命名相关状态
const editingNodeId = ref<string | null>(null) // 正在编辑的节点ID
const editingNodeText = ref('') // 编辑中的节点文本
const editInputRef = ref<HTMLInputElement | null>(null) // 重命名输入框引用

// 4. 设计表弹窗相关状态
const showDesignDialog = ref(false)
const tableName = ref("")
const isClear = computed(() => graphData.value.nodes.length > 0)
const  refreshGraph =()=>{
const lines = graphData.value.lines
  useAppStore.setLines(lines)
  graphRef$.value?.setJsonData(graphData.value)
}
// 初始化图表
onMounted(() => {
   if(treeData.value[0].children && treeData.value[0].children.length> 0 ){
    graphData.value.nodes = treeData.value[0].children.map((it:any)=>it.otherData)
    if(lines.value.length> 0){
      graphData.value.lines = lines.value
    }
  }
  refreshGraph()
  
})
/**
 * 处理右键点击事件：区分节点右键 vs 空白右键
 */
const handleRightClick = (event: MouseEvent, node?: RGNode) => {
  // 阻止浏览器默认右键菜单
  event.preventDefault()
  event.stopPropagation()
  // 先关闭所有已显示的菜单
  closeAllContextMenu()
  // 情况1：点击的是节点（通过事件目标是否包含节点容器类名判断）
  const isClickNode = event.target instanceof HTMLElement &&
    event.target.closest('.graph-node-container')

  if (isClickNode && node) {
    currentNode.value = JSON.parse(isClickNode.getAttribute("data-node")!) // 记录当前点击的节点
    showNodeContextMenu.value = true
    // 菜单定位到鼠标位置
    nodeContextMenuStyle.value = {
      ...nodeContextMenuStyle.value,
      left: `${event.clientX}px`,
      top: `${event.clientY}px`
    }
  }
  // 情况2：点击的是空白处
  else {
    showBlankContextMenu.value = true
    blankContextMenuStyle.value = {
      ...blankContextMenuStyle.value,
      left: `${event.clientX}px`,
      top: `${event.clientY}px`
    }
  }

  // 点击其他地方关闭所有菜单
  const closeMenu = () => {
    closeAllContextMenu()
    document.removeEventListener('click', closeMenu)
  }
  setTimeout(() => document.addEventListener('click', closeMenu), 0)
}
const treeCurrentChange=(node:any)=>{
  useAppStore.setNodeShape(node.id);
  if(treeData.value[0].children && treeData.value[0].children.length> 0 ){
    graphData.value.nodes = treeData.value[0].children.map((it:any)=>it.otherData)
    if(lines.value.length> 0){
      graphData.value.lines = lines.value
    }
  }
  refreshGraph()
}
const handleNodeClick =(node:RGNode)=>{
  treeCurrentChange(node)
}

const customNodeClass=(node:any)=> node?.otherData?.nodeShape ==1?'is-nodeShape' : null

/**
 * 关闭所有右键菜单
 */
const closeAllContextMenu = () => {
  showNodeContextMenu.value = false
  showBlankContextMenu.value = false
}
const saveClick = () => {
  console.log('saveClick', graphData.value);
}

// ------------------------------
// 节点右键菜单：核心功能实现
// ------------------------------
const addNode = () => {
  if (!graphRef$.value) return
  const newNodeId = `node_${Date.now()}`
  const temp = {
    id: newNodeId,
    text: `table_${count.value}`,
    x: parseInt(blankContextMenuStyle.value.left) + 20,
    y: parseInt(blankContextMenuStyle.value.top) + 20,
    color: '#3783c0',
    data: {
      columns: [],
      foreignKey: []
    } // 初始无字段
  }
  graphData.value.nodes.push({
    ...temp,
    nodeShape: 1,
  })
  useAppStore.add(
    {
      label: temp.text,
      id: temp.id,
     otherData: { ...temp,nodeShape: 1,}
    }
  )
  useAppStore.setCount()
refreshGraph()
  closeAllContextMenu()
}

const clearGraph = () => {
  if (!graphRef$.value || !confirm('确定要清空图表吗？')) return
  graphData.value.nodes = []
  graphData.value.lines = []
refreshGraph()
  useAppStore.clear()
  closeAllContextMenu()
}
/**
 * 1. 设计表：打开弹窗并加载当前节点的表结构
 */
const handleDesignTable = () => {
  if (!currentNode.value) return
  const node = currentNode.value
  console.log('handleDesignTable', node)
  // 加载当前节点的表数据到表单
  tableName.value = node.text!

  useFieldStore.setData(node.data!.columns.length ? node.data!.columns : [])
  useForeignKeyStore.setData(node.data!.foreignKey.length ? node.data!.foreignKey : [])

  // 显示设计表弹窗
  showDesignDialog.value = true
  closeAllContextMenu()
}
/**
 * 2. 重命名节点：显示输入框并聚焦
 */
const handleRenameNode = () => {
  if (!currentNode.value) return
  const node = currentNode.value
  // 记录编辑状态
  editingNodeId.value = node.id
  editingNodeText.value = node.text!// 初始值为当前节点文本

  // 等待输入框渲染后聚焦
  nextTick(() => {
    editInputRef.value?.focus()
  })

  closeAllContextMenu()
}
/**
 * 确认重命名（失去焦点或按Enter）
 */
const confirmRename = (nodeId: string) => {
  console.log('nodeId', nodeId);
  const nodeIndex = graphData.value.nodes.findIndex(n => n.id === nodeId)
  if (nodeIndex > -1 && editingNodeText.value.trim()) {
    // 更新节点文本
    graphData.value.nodes[nodeIndex].text = editingNodeText.value.trim()
   refreshGraph()
  }
  useAppStore.editName(nodeId, editingNodeText.value.trim())
  // 取消编辑状态
  editingNodeId.value = null
}
/**
 * 取消重命名（按Esc）
 */
const cancelRename = () => {
  editingNodeId.value = null
}
/**
 * 3. 删除表：移除节点及关联线条
 */
const handleDeleteNode = () => {
  ElMessageBox.confirm('确定要删除吗', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    const nodeId = currentNode.value!.id
    console.log(nodeId);
    // 1. 删除节点
    graphData.value.nodes = graphData.value.nodes.filter(n => n.id !== nodeId)
    // 2. 删除与该节点相关的所有线条（避免残留无效线条）
    graphData.value.lines = graphData.value.lines.filter(
      line => line.from !== nodeId && line.to !== nodeId
    )
    // 刷新图表
    refreshGraph()
    useAppStore.del(nodeId)
    closeAllContextMenu()
    currentNode.value = null // 清空当前节点记录
  }).catch(() => {
    ElMessage.info('你取消了删除')
  })
}
// 设计表结构的取消
const cancel = () => {
  showDesignDialog.value = false
  useForeignKeyStore.clear()
  useFieldStore.clear()
}
// 设计表结构的保存
const saveTableDesign = ({ field, foreignKey }: {
  field: any[]
  foreignKey: any[]
}) => {
  console.log(`field->`, field)
  console.log(`foreignKey->`, foreignKey)

  const nodeId = currentNode.value!.id
  const nodeIndex = graphData.value.nodes.findIndex(n => n.id === nodeId)

  if (nodeIndex > -1) {
    graphData.value.nodes[nodeIndex].data!.foreignKey = foreignKey
    graphData.value.nodes[nodeIndex].data!.columns = field
    if (foreignKey.length > 0) {
      graphData.value.lines.push({
        from: nodeId,
        to: foreignKey[0].fatherTable
      })
    }
    refreshGraph()
  }

  useAppStore.setOtherData(nodeId, {
    field,
    foreignKey
  })
  cancel()
}
</script>

<style lang="scss" scoped>
.el-container {
  height: 100%
}
:deep(.el-tree){
  .is-nodeShape{
    background-color: #f00;
  }
}
.el-footer {
  display: flex;
  justify-content: flex-end;
}

// 关系图基础样式
::v-deep(.relation-graph) {
  .rel-node-checked{
    box-shadow: none;
  }
  .is-nodeShape{
    box-shadow: 0 0 0 8px #ff00004d;
  }
  .rel-map {
    background-size: 30px 30px;
    background-image:
      linear-gradient(90deg, rgba(0, 0, 0, .1) 1px, transparent 0),
      linear-gradient(180deg, rgba(0, 0, 0, .1) 1px, transparent 0);
  }
}

// 右键菜单通用样式
.context-menu {
  width: 120px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  border: 1px solid #e0e0e0;
  padding: 5px 0;

  .menu-item {
    padding: 8px 15px;
    font-size: 14px;
    cursor: pointer;
    transition: background 0.2s;

    &:hover {
      background-color: #f5f5f5;
      color: #1890ff;
    }
  }
}

// 节点表格样式
.c-data-table {
  background-color: #ffffff;
  border-collapse: collapse;
  width: 100%;
  margin-top: 10px;

  td,
  th {
    border: 1px solid #3783c0;
    color: #333333;
    padding: 5px;
    text-align: center;
  }

  td div {
    background-color: #1da9f5;
    color: #ffffff;
    border-radius: 5px;
    padding: 2px 0;
  }
}

// 节点重命名输入框样式
.node-edit-input {
  width: 100%;
  padding: 4px 8px;
  border: 1px solid #1da9f5;
  border-radius: 4px;
  outline: none;
  font-size: 14px;
}
</style>